package 反射;

import 枚举.TestEnum;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflexClassDemo {
    //获取私有构造方法
    public static void reflectPrivateConstructor() {
        //
        try {
            Class<?> c1 = Class.forName("反射.Student");
            Constructor<?> c2 = c1.getDeclaredConstructor(String.class,int.class);
            //因为是私有的，需要程序员确认
            c2.setAccessible(true);
            //调用newInstance创建类的实例
            /**
             * 是通过c2调用的实例化方法
             */
           Student s = (Student) c2.newInstance("八戒",66);
            System.out.println(s);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
    public static void reflectNewInstance() {
        //通过这个方法获取类
        try {
            //常用
            Class<?> c1 = Class.forName("反射.Student");
            //返回类型时object进行强转
             Student str = (Student) c1.newInstance();

            System.out.println("学生对象"+str);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }


    }
    //反射私有属性
    public static void reflectPrivateField() {
        try {
            Class<?> c1 = Class.forName("反射.Student");
            //获取私有的属性
            Field field = c1.getDeclaredField("name");
            //程序员确认
            field.setAccessible(true);
            //实例化一个类
            Student student = (Student) c1.newInstance();
            //传入类，和要修改的属性
            field.set(student,"唐老鸭");
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
    //反射私有方法
    public static void reflectPrivateMethod() {
        //先获取这个类
        try {
            Class<?> c1 = Class.forName("反射.Student");
            Method method = c1.getDeclaredMethod("function", String.class);
            //程序员确认为true
            method.setAccessible(true);
            //实例化这个类
            Student student = (Student) c1.newInstance();
            //直接调用这个方法
             method.invoke(student,"猪猪侠");
          //  System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static void reflectPrivateConstructor2() {
        try {
            Class<?> classStudent = Class.forName("枚举.TestEnum");
//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类是提供了两个参数分别是String和int。
            Constructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class,int.class);
//设置为true后可修改访问权限
            declaredConstructorStudent.setAccessible(true);
            TestEnum testEnum = (TestEnum)declaredConstructorStudent.newInstance("绿色",666);
            System.out.println("获得枚举的私有构造函数："+testEnum);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    public static void reflectPrivateConstructor1() {
        try {
            Class<?> classStudent = Class.forName("枚举.TestEnum");
            //获取私有构造方法
            Constructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor
                    (String.class,int.class,String.class,int.class);
            //无法以反射方式创建枚举对象,error,枚举通过反射在类外无法拿到
            declaredConstructorStudent.setAccessible(true);
            //不是靠classStudent调用的newInstance
               TestEnum testEnum = (TestEnum) declaredConstructorStudent.newInstance("父类参数",11,"张三",1);
            System.out.println("获得枚举的私有构造函数："+testEnum);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //打印bit和18，因为以及重写了toString，又因为年龄和姓名都进行了初始化
       // reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        //reflectPrivateMethod();
        reflectPrivateConstructor1();
    }
}
